package xx.iverson.video_manage.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import xx.iverson.video_manage.entity.CategoryLevel1;
import xx.iverson.video_manage.entity.CategoryLevel2;
import xx.iverson.video_manage.entity.Video;
import xx.iverson.video_manage.mapper.IndexMapper;
import xx.iverson.video_manage.mapper.VideoMapper;
import xx.iverson.video_manage.util.VideoUploadUtil;

import javax.annotation.Resource;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * Video management controller.
 */
@Controller
@RequestMapping("/admin/video")
public class VideoManageController implements CommandLineRunner {

    private static final String UPLOAD_DIR = "D:/video_image/";
    @Autowired
    private VideoUploadUtil videoUploadUtil;

    @Autowired
    private VideoMapper videoService;

    // 静态代码块，在类加载时执行一次
    static {
        try {
            Path uploadPath = Paths.get(UPLOAD_DIR);
            if (!Files.exists(uploadPath)) {
                Files.createDirectories(uploadPath);
                // 创建 readme.txt 文件
                Path readmeFile = uploadPath.resolve("readme.txt");
                Files.write(readmeFile, "该文件夹为视频管理系统图片文件夹，请勿删除！".getBytes());
            }
        } catch (IOException e) {
            throw new RuntimeException("Failed to initialize upload directory", e);
        }
    }

    @Resource
    private IndexMapper indexMapper;

    /**
     * 显示视频管理页面，加载所有视频、一级分类和二级分类信息
     *
     * @param model 用于向视图传递数据的模型对象
     * @return 返回视频管理页面视图名称
     */
    @GetMapping
    public String manageVideos(Model model) {
        model.addAttribute("videos", videoService.selectAll());
        model.addAttribute("categories", videoService.selectOne());
        model.addAttribute("subcategories", videoService.selectTwo());
        model.addAttribute("title", indexMapper.selectTitle());
        return "video_manage";
    }


    /**
     * 检查文件名是否已存在
     */
    @GetMapping("/check-filename")
    public ResponseEntity<Map<String, Object>> checkFileNameExists(@RequestParam String fileName) {
        Map<String, Object> result = new HashMap<>();

        try {
            // 查询数据库中是否已存在相同文件名的视频
            boolean exists = videoService.checkFileNameExists(fileName);
            result.put("exists", exists);
            result.put("success", true);
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "检查文件名失败: " + e.getMessage());
        }

        return ResponseEntity.ok(result);
    }

    // 添加分片上传相关接口
    @GetMapping("/chunk")
    public ResponseEntity<Map<String, Object>> checkChunk(
            @RequestParam String fileMd5,
            @RequestParam Integer chunkIndex) {

        Map<String, Object> result = new HashMap<>();
        boolean exists = videoUploadUtil.checkChunk(fileMd5, chunkIndex);
        result.put("exists", exists);

        return ResponseEntity.ok(result);
    }

    @GetMapping("/chunks")
    public ResponseEntity<Map<String, Object>> getUploadedChunks(
            @RequestParam String fileMd5) {

        Map<String, Object> result = new HashMap<>();
        Integer[] uploadedChunks = videoUploadUtil.getUploadedChunks(fileMd5);
        result.put("uploadedChunks", uploadedChunks);

        return ResponseEntity.ok(result);
    }

    @PostMapping("/upload/chunk")
    public ResponseEntity<Map<String, Object>> uploadChunk(
            @RequestParam("file") MultipartFile file,
            @RequestParam String fileMd5,
            @RequestParam Integer chunkIndex,
            @RequestParam Integer totalChunks) {

        Map<String, Object> result = new HashMap<>();

        try {
            boolean success = videoUploadUtil.processChunk(file, fileMd5, chunkIndex, totalChunks);
            result.put("success", success);
            result.put("message", "分片上传成功");
        } catch (IOException e) {
            result.put("success", false);
            result.put("message", "分片上传失败: " + e.getMessage());
        }

        return ResponseEntity.ok(result);
    }

    @PostMapping("/merge")
    public ResponseEntity<Map<String, Object>> mergeChunks(
            @RequestParam String fileMd5,
            @RequestParam String fileName,
            @RequestParam String fileType,
            @RequestParam Long fileSize) {

        Map<String, Object> result = new HashMap<>();

        try {
            String storageName = videoUploadUtil.mergeChunks(fileMd5, fileName);
            result.put("success", true);
            result.put("message", "文件上传成功");
            result.put("storageName", storageName);
        } catch (IOException e) {
            result.put("success", false);
            result.put("message", "文件合并失败: " + e.getMessage());
        }

        return ResponseEntity.ok(result);
    }

    // 修改添加视频的方法
    @PostMapping("/add")
    public String addVideo(@ModelAttribute Video video,
                           @RequestParam("file") MultipartFile file,
                           Model model) throws IOException {

        String uploadMode = video.getUploadMode();

        // 处理上传模式
        if ("local".equals(uploadMode)) {
            // 本地上传模式，使用 storageName 作为播放URL
            video.setUrl(video.getStorageName());
        } else if ("network".equals(uploadMode)) {
            // 网络视频模式，保持原有URL
            // 不需要额外处理
        } else if ("server".equals(uploadMode)) {
            // 服务器复制模式，保持原有URL
            // 不需要额外处理
        }

        // 处理封面图片
        if (!file.isEmpty()) {
            String originalFilename = file.getOriginalFilename();
            String fileExtension = null;
            if (originalFilename != null) {
                fileExtension = originalFilename.substring(originalFilename.lastIndexOf("."));
            }
            String newFileName = UUID.randomUUID() + fileExtension;
            Path filePath = Paths.get(UPLOAD_DIR + newFileName);
            Files.copy(file.getInputStream(), filePath);
            video.setImage(newFileName);
        }

        // 插入新视频记录到数据库
        videoService.insert(video);
        model.addAttribute("videos", videoService.selectAll());

        return "redirect:/admin/video";
    }

    /**
     * 更新指定ID的视频信息
     *
     * @param id    要更新的视频ID
     * @param video 包含更新信息的视频实体对象
     * @return 更新成功后重定向到视频管理页面
     * @throws IOException 如果文件操作过程中发生IO异常
     */
    @PostMapping("/update/{id}")
    public String updateVideo(@PathVariable Long id, @ModelAttribute Video video) throws IOException {
        video.setVideoId(Math.toIntExact(id));
        videoService.update(video);
        return "redirect:/admin/video";
    }

    /**
     * 删除指定ID的视频，并删除其关联的封面图片（如果存在）
     *
     * @param id 要删除的视频ID
     * @return 删除成功后重定向到视频管理页面
     */
    @PostMapping("/delete/{id}")
    public String deleteVideo(@PathVariable Long id) {
        Video video = videoService.selectById(id);
        if (video.getImage() != null && !video.getImage().isEmpty()) {
            try {
                Files.deleteIfExists(Paths.get(UPLOAD_DIR + video.getImage()));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        videoService.deleteById(id);
        return "redirect:/admin/video";
    }

    /**
     * 删除指定ID的一级分类，若该分类下有子分类则不执行删除
     *
     * @param id 要删除的一级分类ID
     * @return 删除成功或失败后重定向到视频管理页面
     */
    @PostMapping("/delete/one/{id}")
    public String deleteOne(@PathVariable Long id) {
        if (videoService.selectByOneId(id) != 0) {
            return "redirect:/admin/video";
        }
        videoService.deleteOneById(id);
        return "redirect:/admin/video";
    }

    /**
     * 删除指定ID的二级分类，若该分类下有视频则不执行删除
     *
     * @param id 要删除的二级分类ID
     * @return 删除成功或失败后重定向到视频管理页面
     */
    @PostMapping("/delete/two/{id}")
    public String deleteTwo(@PathVariable Long id) {
        if (videoService.selectByTwoId(id) != 0) {
            return "redirect:/admin/video";
        }
        videoService.deleteTwoById(id);
        return "redirect:/admin/video";
    }

    /**
     * 实现CommandLineRunner接口的方法，在应用启动时执行初始化逻辑（当前为空实现）
     *
     * @param args 启动参数
     * @throws Exception 启动过程中可能抛出的异常
     */
    @Override
    public void run(String... args) throws Exception {

    }

    /**
     * 添加新的一级分类
     *
     * @param categoryLevel1 一级分类实体对象
     * @param model          用于向视图传递数据的模型对象
     * @return 添加成功后重定向到视频管理页面
     * @throws IOException 如果文件操作过程中发生IO异常
     */
    @PostMapping("/addOne")
    public String addOne(@ModelAttribute CategoryLevel1 categoryLevel1,
                         Model model) throws IOException {
        // 插入新视频记录到数据库
        videoService.insertOne(categoryLevel1);
        // 刷新模型中的videos列表以反映最新的变化
        model.addAttribute("videos", videoService.selectAll());
        model.addAttribute("categories", videoService.selectOne());
        model.addAttribute("subcategories", videoService.selectTwo());
        return "redirect:/admin/video";
    }


    /**
     * 添加新的二级分类
     *
     * @param categoryLevel2 二级分类实体对象
     * @param model          用于向视图传递数据的模型对象
     * @return 添加成功后重定向到视频管理页面
     * @throws IOException 如果文件操作过程中发生IO异常
     */
    @PostMapping("/addTwo")
    public String addTwo(@ModelAttribute CategoryLevel2 categoryLevel2,
                         Model model) throws IOException {
        // 插入新视频记录到数据库
        videoService.insertTwo(categoryLevel2);
        // 刷新模型中的videos列表以反映最新的变化
        model.addAttribute("videos", videoService.selectAll());
        model.addAttribute("categories", videoService.selectOne());
        model.addAttribute("subcategories", videoService.selectTwo());
        return "redirect:/admin/video";
    }

    /**
     * 更新一级分类信息
     *
     * @param categoryLevel1 一级分类实体对象
     * @param model          用于向视图传递数据的模型对象
     * @return 更新成功后重定向到视频管理页面
     * @throws IOException 如果文件操作过程中发生IO异常
     */
    @PostMapping("/updateOne")
    public String updateOne(@ModelAttribute CategoryLevel1 categoryLevel1,
                         Model model) throws IOException {
        // 插入新视频记录到数据库
        videoService.updateOne(categoryLevel1);
        // 刷新模型中的videos列表以反映最新的变化
        model.addAttribute("videos", videoService.selectAll());
        model.addAttribute("categories", videoService.selectOne());
        model.addAttribute("subcategories", videoService.selectTwo());
        return "redirect:/admin/video";
    }

    /**
     * 更新二级分类信息
     *
     * @param categoryLevel2 二级分类实体对象
     * @param model          用于向视图传递数据的模型对象
     * @return 更新成功后重定向到视频管理页面
     * @throws IOException 如果文件操作过程中发生IO异常
     */
    @PostMapping("/updateTwo")
    public String updateTwo(@ModelAttribute CategoryLevel2 categoryLevel2,
                         Model model) throws IOException {
        // 插入新视频记录到数据库
        videoService.updateTwo(categoryLevel2);
        // 刷新模型中的videos列表以反映最新的变化
        model.addAttribute("videos", videoService.selectAll());
        model.addAttribute("categories", videoService.selectOne());
        model.addAttribute("subcategories", videoService.selectTwo());
        return "redirect:/admin/video";
    }

    /**
     * 更新网站标题
     *
     * @param newTitle 新的标题内容
     * @param model    用于向视图传递数据的模型对象
     * @return 更新成功后重定向到视频管理页面
     */
    // 更新标题的接口
    @PostMapping("/edit")
    public String editTitle(@RequestParam("title") String newTitle,Model model) {
        videoService.updateTitle(newTitle);
        model.addAttribute("title", indexMapper.selectTitle());
        return "redirect:/admin/video";
    }
}